#include "uart.h"
#include "uart_msg_queue.h"
#include "websocketserver.h"
#include "wait_response_list.h"
#include "sql.h"
#include "gprs.h"

unsigned char cmd_uart[5];//命令存储缓冲区
unsigned char data_array[1];//数据接收缓冲区，串口中断，每次接收一个字节
unsigned char uartnum                   = 0;//串口流号
unsigned char uart_fd                   = 0;//串口设备文件描述符
unsigned char uart_enable_flag          = 0;//串口使能标志位 0 串口未开启工作，1 串口开启工作，为了降低功耗，在不需要串口时关闭
unsigned char uart_send_flag            = 0; //串口数据发送标志位 0 无数据发送，1 有数据发送
unsigned char uart_recive_All           = 0;//串口接收完成标志 0 没有全部接收完成，1 全部接收完成
unsigned char olddata                   = 0;//记录上一个接收数据
unsigned char ACK_recive_satus          = 0;//ack返回值值状态 0 ack报错  ；1 ack成功
unsigned char Ack_recive_enable         = 0;//应答接收使能标志 0 禁止接收使能 ；1开启接收使能;2进入重收功能，上行出错
unsigned char ACC_resend                = 0;//重发次数累加器
static unsigned short uart_recive_l     = 0;//已经接收数据长度缓存
unsigned char needsuccessack_flag       = NOACK;//发送应答标志位 NOACK:不发送 SuccsACK:发送成功ACK FailACK:发送错误ACK
unsigned char Timeout1Sec_Uart_StarFlag = 0;//超时重传
unsigned char sendsuccessflag           = 0;
uart_communication_dmwz uart_communicate_rec_buf  = {0,0,0,{0},0};//数据接收缓冲区
uart_communication_dmwz uart_communicate_send_buf = {0,0,1,{0},0};//数据发送缓冲区 no_use初始化为1 响应数组的索引从1开始

unsigned char ack_erro[3]  = {0x5a, 0xa5, 0x01};//成功接收应答
unsigned char ack_succs[3] = {0x5a, 0xa5, 0x00};//错误接收应答
UART_MSG_Queue_Header *UART_MSG_Receive_Que = NULL;//串口消息接收队列头结点

sem_t Sem_UART_Que;//接收队列读写锁
//int uart_msgid;//消息队列标识符

char *sql_table[]     = {"ZB_Bedroom", "ZB_Livingroom", "ZB_Kitchen", "ZB_Bathroom"};
//sql表格
char *sensor_table[]  = {NULL, NULL, "Psst_Table", NULL, NULL, NULL, "Light_Table", "Temperature_Table", "Humidity_Table", "Door_Table", "Fan_Table", "Beep_Table", "Smoke_Table", "Calorifier_Table", "Curtain_Table"};
char *devcfg_table    = "DeviceCfg";//设备配置表

/** CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */
int crc16_table[] =
{
	0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
	0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
	0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
	0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
	0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
	0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
	0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
	0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
	0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
	0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
	0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
	0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
	0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
	0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
	0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
	0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
	0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
	0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
	0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
	0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
	0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
	0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
	0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
	0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
	0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
	0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
	0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
	0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
	0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
	0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
	0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
	0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};

static inline unsigned short crc16_byte(unsigned short crc, const unsigned char data)
{
    return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff];
}

unsigned short bd_crc16(unsigned short crc, unsigned char const *buffer, int len)
{
    while (len--)
        crc = crc16_byte(crc, *buffer++);
    return crc;
}

/*********************************************************************
 * @fn      serial_init
 *
 * @brief   串口初始化设置，波特率、流控制、停止位数、数据位、校验位
 *
 * @param   fd,串口设备文件的文件描述符
 *
 * @return  none
 */
void serial_init(int fd)
{
	struct termios options;
	tcgetattr(fd, &options);

	options.c_cflag |= ( CLOCAL | CREAD );
	options.c_cflag &= ~PARENB;
	options.c_iflag &= ~INPCK;

	options.c_cflag &= ~CSIZE;
	options.c_cflag &= ~CRTSCTS;

	options.c_cflag |= CS8;
	options.c_cflag &= ~CSTOPB;
	options.c_iflag |= IGNPAR;
	options.c_iflag &= ~(ICRNL | IXON);

	options.c_oflag &= ~OPOST;
	options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

	cfsetispeed(&options, B115200);
	cfsetospeed(&options, B115200);
	tcsetattr(fd,TCSANOW,&options);
}

/*********************************************************************
 * @fn      usart_setup
 *
 * @brief   串口初始化函数
 *
 * @param   none
 *
 * @return  成功：0 失败：-1
 */
int usart_setup(const unsigned char *uart_root)
{
	UART_MSG_Receive_Que = UART_MSG_Queue_Init();//初始化接收队列

	//O_NONBLOCK设置为非阻塞模式，在read时不会阻塞住，在读的时候将read放在while循环中
	uart_fd=open(uart_root, O_RDWR | O_NOCTTY | O_NONBLOCK);
	serial_init(uart_fd);

#ifdef UART_Debug
 	int pins;
	ioctl(uart_fd,TIOCMGET,&pins);
	pins=pins|TIOCM_DTR;
	ioctl(uart_fd,TIOCMSET,&pins);
#endif

	return 0;
}

/*********************************************************************
 * @fn      uart_send_Bty
 *
 * @brief   串口数据多字节发送
 *
 * @param   buf:数据包首地址 len:数据长度
 *
 * @return  none
 */
void uart_send_Bty(const unsigned char* buf, const unsigned short len)
{
	write(uart_fd, buf, len);
}

/*********************************************************************
 * @fn      usart_send_nonblocking
 *
 * @brief   串口单字节发送函数
 *
 * @param   x:数据字节
 *
 * @return  none
 */
void usart_send_nonblocking(const char x)
{
	write(uart_fd,&x,1);
}

/*********************************************************************
 * @fn      usart_recv_nonblocking
 *
 * @brief   串口单字节接收
 *
 * @param   x:数据接收缓冲区
 *
 * @return  返回读取到的字节数
 */
int usart_recv_nonblocking(char *x)
{
	return read(uart_fd, x, 1);
}

/*********************************************************************
 * @fn      usart_recv_multiple_Byte
 *
 * @brief   串口读取多个字节函数
 *
 * @param   buf:数据接收缓冲区 len:接收字节数量
 *
 * @return  返回读取到的字节数
 */
int usart_recv_multiple_Byte(unsigned char *buf, const int len)
{
	return read(uart_fd, buf, len);
}


/*********************************************************************
 * @fn      UART_Reciver_Data
 *
 * @brief   串口数据接收 并判断
 *
 * @param   none
 *
 * @return  none
 */
void UART_Recive_Data(void)
{
	int res;

	if(olddata!=uart_databytes)//上一个数据未处理完成不进行接收
    {
        //串口数据接收,无数据直接结束
        if(usart_recv_nonblocking(data_array)<=0)
        {
            return;
        }

        /*
         *	判断上一个数据来确定当前接收的数据的值
         *  普通数据包格式:
         *  uart_0xa5
         *  uart_0x5a
         *  uart_length_H
         *  uart_length_L
         *  uart_cmd
         *  uart_nouseful
         */
        switch(olddata)
        {
            case uart_0xa5://已经收到数据头0xa5
				//printf("Get 0xa5\n");
                if(data_array[0]==0x5a)
                {
                    //接收数据头完成准备，接收长度字节
                    olddata=uart_0x5a;
                }
                else
                {
                    //接收字节错误，从新等待接收数据头
                    olddata=0;
                }
            break;

            case uart_0x5a://已经收到数据头0x5a,数据头已经全部接收完成且正确
				//printf("Get 0x5a LH:%d\n", data_array[0]);
                uart_communicate_rec_buf.length = data_array[0];//存储长度字节高8位
                uart_communicate_rec_buf.length = uart_communicate_rec_buf.length<<8;
                olddata=uart_length_H;
            break;

            case uart_length_H://已经收到长度字节高8位,
				//printf("Get LH LL:%d\n", data_array[0]);
                uart_communicate_rec_buf.length = (uart_communicate_rec_buf.length)|data_array[0];//存储长度字节低8位
                olddata=uart_length_L;
            break;

            case uart_length_L://长度字节接收完成
				//printf("Get LL cmd:%d\n", data_array[0]);
                uart_communicate_rec_buf.cmd = data_array[0];//存储命令字节
                olddata=uart_cmd;
            break;

            case uart_cmd://命令字节接收完成
				//printf("Get CMD no_use:%d\n", data_array[0]);
                uart_communicate_rec_buf.no_use = data_array[0];//存储保留字节
                uart_recive_l=0;//已接收的数据长度清零 准备接收真正的数据
                olddata=uart_nouseful;
            break;

            case uart_nouseful://保留字节接收完成
				//printf("Get NUF\n");
                uart_communicate_rec_buf.data[uart_recive_l]=data_array[0];//接收数据区数据
                uart_recive_l++;

                //循环判断接收数据字节数 多字节接收
                while(uart_recive_l!=(uart_communicate_rec_buf.length-2))
                {
                    res = usart_recv_multiple_Byte((uart_communicate_rec_buf.data+uart_recive_l), (uart_communicate_rec_buf.length-2-uart_recive_l));
                    uart_recive_l += res;
                }
				//printf("%s\n", uart_communicate_rec_buf.data);

                if(uart_recive_l==(uart_communicate_rec_buf.length-2))//接收完成 uart_communicate_rec_buf.length-2
                {
                    uart_recive_All=1;//接收完成标志位置 olddata与uart_recive_All的清零都要在接收数据处理完以后进行
                    olddata=uart_databytes;
                    uart_communicate_rec_buf.crc16=uart_communicate_rec_buf.data[uart_recive_l-2];
                    uart_communicate_rec_buf.crc16=(uart_communicate_rec_buf.crc16)<<8;
                    uart_communicate_rec_buf.crc16=uart_communicate_rec_buf.crc16|uart_communicate_rec_buf.data[uart_recive_l-1];
                }
            break;

            //case uart_databytes://数据已经接收完成，若没有处理完当前数据时，再有数据接收，不进行存储
            //break;

            case uart_first_0x5a://已经接收到ack数据头5a
                if(data_array[0]==0xa5)
                {
                    //接收数据头完成准备，接收状态字节
                    olddata=uart_secend_0xa5;
                }
                else
                {
                    //接收字节错误，从新等待接收数据头
                    olddata=0;
                }
            break;

            case uart_secend_0xa5://ACK数据头接收完成
                if(data_array[0]==0x00)
                {
                    //ACK成功接收
                    ACK_recive_satus=SuccsACK;
					//printf("get Success ACK\n");
                }
                else
                {
                    ACK_recive_satus=FailACK;
					printf("get Fail ACK\n");
                }
            break;

            default://等待接收数据头字节
                if(data_array[0]==0xa5&&olddata==0)
                {
                    //接收到正常数据包数据头，准备接收下一字节数据头
                    olddata=uart_0xa5;
                }
                if(data_array[0]==0x5a&&olddata==0)
                {
                    //接收到ACK数据头，准备接收下一字节数据头
                    olddata=uart_first_0x5a;
                }
            break;
        }
	}
}

/*****************************APP 协议层*****************************/


/*********************************************************************
 * @fn      uart_send
 *
 * @brief   串口发送函数,将串口缓冲区中的内容发送出去
 *
 * @param   none
 *
 * @return  none
 */
void uart_send(void)
{
    unsigned char len[2]={0,0};

	//printf("send data\n");

    len[0]=0x00ff&((uart_communicate_send_buf.length)>>8);
	len[1]=0x00ff&(uart_communicate_send_buf.length);

    //数据头发送
	usart_send_nonblocking(0xa5);
	usart_send_nonblocking(0x5a);
    //数据长度发送
	usart_send_nonblocking(len[0]);
	usart_send_nonblocking(len[1]);
	//命令字节发送
	usart_send_nonblocking(uart_communicate_send_buf.cmd);
	//预留字节发送
	usart_send_nonblocking(uart_communicate_send_buf.no_use);
	//数据区发送
	uart_send_Bty(uart_communicate_send_buf.data, ((uart_communicate_send_buf.length)-2));
}

/*********************************************************************
 * @fn      CRC16_check
 *
 * @brief   CRC校验
 *
 * @param   none
 *
 * @return  成功:0 失败:1
 */
unsigned char CRC16_check(void)
{
  unsigned short crc16=0;
  unsigned char  data[4];
  unsigned char  res=0;
  unsigned char buf[256];

  data[0] = 0x00ff&((uart_communicate_rec_buf.length)>>8);
  data[1] = 0x00ff&((uart_communicate_rec_buf.length));
  data[2] = uart_communicate_rec_buf.cmd;
  data[3] = uart_communicate_rec_buf.no_use;

  memcpy(buf, data, 4);
  memcpy(buf+4, uart_communicate_rec_buf.data, uart_communicate_rec_buf.length-4);
  crc16 = bd_crc16(0, buf, uart_communicate_rec_buf.length);

  if(crc16!=uart_communicate_rec_buf.crc16)
  {
      res = 1;
  }

  return res;
}

/*********************************************************************
 * @fn      CRC16_Uart_send
 *
 * @brief   CRC校验值计算
 *
 * @param   none
 *
 * @return  CRC校验值
 */
unsigned short CRC16_Uart_send(void)
{
  unsigned short crc16=0;
  unsigned char data[4];
  unsigned char buf[256];

  data[0]=0x00ff&((uart_communicate_send_buf.length)>>8);
  data[1]=0x00ff&((uart_communicate_send_buf.length));
  data[2]=uart_communicate_send_buf.cmd;
  data[3]=uart_communicate_send_buf.no_use;

  memcpy(buf, data, 4);
  memcpy(buf+4, uart_communicate_send_buf.data, uart_communicate_send_buf.length-4);
  crc16 = bd_crc16(0, buf, uart_communicate_send_buf.length);

  return crc16;
}

/*********************************************************************
 * @fn      CmdSendUart
 *
 * @brief   将数据写入串口缓冲区，等待发送
 *
 * @param   none
 *
 * @return  none
 */
void CmdSendUart(unsigned char Cmd_uart,unsigned char *apdubuf,unsigned short apdulength)
{
    char str_mac[32];
    char mac[32];

	uart_communicate_send_buf.length=1+1+apdulength+2;
	uart_communicate_send_buf.cmd=Cmd_uart;//命令


	++uart_communicate_send_buf.no_use;//no_use表示每个数据包的响应号
	if(uart_communicate_send_buf.no_use==0)//溢出
	{
		uart_communicate_send_buf.no_use = 1;//响应数据索引从1开始
	}

	memcpy(str_mac, apdubuf, 8);
	str_mac[8]='\0';
	WAIT_RES_ARRAY[uart_communicate_send_buf.no_use] = 1;//响应数组对应位置1，等待响应
	insert_node(str_mac, Cmd_uart, uart_communicate_send_buf.no_use);//加入消息等待响应链表
	str_transition_mac(str_mac, mac);
	printf("insert list mac:%s\n", mac);

	memcpy(uart_communicate_send_buf.data, apdubuf, apdulength);//将数据拷贝到串口发送缓冲区中

	uart_communicate_send_buf.crc16=CRC16_Uart_send();//计算校验位
	uart_communicate_send_buf.data[apdulength]   = 0x00ff&(uart_communicate_send_buf.crc16>>8);//校验位存放
	uart_communicate_send_buf.data[apdulength+1] = 0x00ff&(uart_communicate_send_buf.crc16);

	uart_send_flag      = 1;//串口发送标志置位，串口发送数据
}

/*********************************************************************
 * @fn      Uart_cmdprogam
 *
 * @brief   串口数据处理
 *
 * @param   none
 *
 * @return  none
 */
void Uart_cmdprogam(void)
{
    uartmsg msg;

	/*
	 *	从串口数据包中提取数据保存到队列中
	 */
	msg.cmd   = uart_communicate_rec_buf.cmd;
	msg.count = uart_communicate_rec_buf.length-4;
	memcpy(msg.data, uart_communicate_rec_buf.data, msg.count);

	msg.data[msg.count]                             = '\0';
	WAIT_RES_ARRAY[uart_communicate_rec_buf.no_use] = 0;//响应数组对应位置清0

	//sem_wait(&Sem_UART_Que);
	//读写锁
	poperation(sem_uart_rec_dat_wr_id, g_sem_id);
	UART_MSG_Queue_Enqueue(UART_MSG_Receive_Que, msg);//将数据包入队
	voperation(sem_uart_rec_dat_wr_id, g_sem_id);
	//sem_post(&Sem_UART_Que);
}

/*********************************************************************
 * @fn      UART_Recive_Data_Handle
 *
 * @brief   串口数据处理
 *
 * @param   none
 *
 * @return  none
 */
void UART_Recive_Data_Handle(void)
{
	if((uart_recive_All==1)||(ACK_recive_satus!=NOACK))//数据接收已完成/有应答数据
	{
		TP_CLOSE();//关闭计时器，准备从新计时
		Timeout1Sec_Uart_StarFlag=TimeClose;//关闭1秒超时定时器
		if(uart_recive_All==1)//成功接收到数据
		{
			ACC_resend=0;//重发累计清零
		    if(CRC16_check()==0)//接收数据校验是否正确
			{
				Uart_cmdprogam();//根据指令进行处理
                needsuccessack_flag = SuccsACK;//发送ACK标志位 表示发送成功接收的ACK
			}
			else
			{
                needsuccessack_flag = FailACK;//发送ACK标志位 表示发送错误接收的ACK
			}
		}
		else//成功接收到ACK包
		{
			//接收到错误应答，对原有数据进行重发
			if(ACK_recive_satus==FailACK)
			{
				/*
				 *  重发次数ACC_resend累加
				 *  判断是否达到最大重发次数
				 *  	达到：则将计数变量ACC_resend清零 放弃此次数据的发送
				 *      未达到：将发送数据标志位uart_send_flag置1 重新发送数据
				 */
				 //printf("Get FA\n");
				ACC_resend++;
				if(ACC_resend<MAX_resend)
				{
					uart_send_flag=1;
				}
				else
				{
					ACC_resend=0;
				}
			}

			//接收到正确应答
			if(ACK_recive_satus==SuccsACK)
			{
				sendsuccessflag=0;//sendsuccessflag置0 表示此次数据包发送成功
				//printf("Get SA\n");
				ACC_resend=0;//重发累计清零
			}
		}

		ACK_recive_satus=0;//清ACK接收状态
		uart_recive_All=0;//清接收完成标志
		olddata=0;//清接收流程状态
	}
	else
	{
		//无应答数据 wait send ack
		if(sendsuccessflag==1)
		{
			//判断超时1秒定时器是否开启
			if(Timeout1Sec_Uart_StarFlag==TimeClose)//未打开
			{
				TP_START(); //开启定时器
				Timeout1Sec_Uart_StarFlag=TimeOpen;
			}
			else//已打开
			{
				//判断是否超时 超时重发
				if(CheckTP()==0)//超时
				{
					TP_CLOSE();//关闭计时器，准备从新计时
					Timeout1Sec_Uart_StarFlag=TimeClose;//关闭1秒超时定时器
					ACC_resend++;//重发次数累加
					//判断是否达到最大次数
					if(ACC_resend<MAX_resend)//没有达到最大次数
					{
						uart_send_flag=1;//发送数据标志位uart_send_flag置1 重发数据
					}
					else
					{
						ACC_resend=0;//重发累计清零
						sendsuccessflag=3;//重发失败 放弃发送 串口出现问题
					}
				}
				else
				{}//无超时，继续等待ACK或应答数据
			}
		}
	}

}

/*********************************************************************
 * @fn      Pthread_UART_Send
 *
 * @brief   串口发送线程函数
 *
 * @param   arg：
 *
 * @return  none
 */
void *Pthread_UART_Send(void *arg)
{
	int res;
    uartmsg msg;

    while(1)
    {
        //开始第一次发送/上一次发送完成
        if(sendsuccessflag==0)
		{
			poperation(sem_msg_queue_qt_id, g_sem_id);//消息队列读写锁
			res = msgrcv(g_msgid, (void *)&msg, sizeof(msg)-sizeof(long int), MSG_QUEUE_ZB_TYPE, IPC_NOWAIT);
			voperation(sem_msg_queue_qt_id, g_sem_id);

			if(res>0)
			{
				//有需要发送的串口消息
				printf("get msg\n");
				CmdSendUart(msg.cmd, msg.data, msg.count);
			}
		}

		//发送接收到的数据/重发数据
        if(uart_send_flag==1)
        {
            uart_send();//发送数据
            uart_send_flag=0;//发送标志清零
            sendsuccessflag=1;//表示未发送成功 等待应答
        }

        //发送成功ACK
        if(needsuccessack_flag==SuccsACK)
        {
			//printf("Send SACK\n");
            uart_send_Bty(ack_succs, 3);
            needsuccessack_flag=NOACK;//清除标志位
        }

        //发送错误ACK
        if(needsuccessack_flag==FailACK)
        {
			printf("Send FACK\n");
            uart_send_Bty(ack_erro,3);
            needsuccessack_flag=NOACK;//清除标志位
        }
    }
}

/*********************************************************************
 * @fn      Pthread_UART_Receive
 *
 * @brief   串口接收线程函数
 *
 * @param   arg：
 *
 * @return  none
 */
void *Pthread_UART_Receive(void *arg)
{
	//timer_init();

	while(1)
    {
		UART_Recive_Data();
		UART_Recive_Data_Handle();
	}
}

/*********************************************************************
 * @fn      Pthread_UART_Receive_Data_Handle
 *
 * @brief   处理接收队列中的命令线程函数
 *
 * @param   arg：
 *
 * @return  none
 */
void *Pthread_UART_Receive_Data_Handle(void *arg)
{
    UART_MSG_Queue_Node *node;

	while(1)
    {
		//sem_wait(&Sem_UART_Que);
		poperation(sem_uart_rec_dat_wr_id, g_sem_id);
        node = UART_MSG_Queue_Dequeue(UART_MSG_Receive_Que);
		voperation(sem_uart_rec_dat_wr_id, g_sem_id);
		//sem_post(&Sem_UART_Que);
        if(node!=NULL)
        {
            switch(node->uart_msg.cmd)
            {
                /* 这里做接受到串口信息时的处理 */
				//光强数据
				case CMD_PSST:
					zb_sensor_llumination_handle(&node->uart_msg);
					break;
				//灯光数据
				case CMD_LIGHT:
					zb_sensor_light_handle(&node->uart_msg);
					break;
				//温度数据
				case CMD_TEMPERATURE:
					zb_sensor_temp_handle(&node->uart_msg);
					break;
				//湿度数据
				case CMD_HUMIDITY:
					zb_sensor_humidity_handle(&node->uart_msg);
					break;
				//门数据
				case CMD_DOOR:
					zb_sensor_door_handle(&node->uart_msg);
					break;
				//风扇数据
				case CMD_RELAY:
					zb_sensor_fan_handle(&node->uart_msg);
					break;
				//蜂鸣器数据
				case CMD_BEEP:
					zb_sensor_beep_handle(&node->uart_msg);
					break;
				//烟雾传感器数据
				case CMD_SMOKE:
					zb_sensor_smoke_handle(&node->uart_msg);
					break;
				//热水器数据
				case CMD_CALORIFIER:
					zb_sensor_calorifier_handle(&node->uart_msg);
					break;
				//窗帘数据
				case CMD_CURTAIN:
					zb_sensor_curtain_handle(&node->uart_msg);
					break;
                //设备上线
                case ZB_DEV_ONLINE:
					zb_dev_online_handle(&node->uart_msg);
                    break;
                //设备下线
                case ZB_DEV_OFFLINE:
					zb_dev_offline_handle(&node->uart_msg);
                    break;
            }

            free((void *)node);//释放
        }
    }
}

/*********************************************************************
 * @fn      zb_dev_online_handle
 *
 * @brief   设备上线处理函数
 *
 * @param   msg:消息
 *
 * @return  none
 */
void zb_dev_online_handle(uartmsg *msg)
{
	char dat_buf[5][32];
	char status[16];
	char update_status[128];
	char type[5] = {SQL_FIEL_TYPE_STR, SQL_FIEL_TYPE_STR, SQL_FIEL_TYPE_INT, SQL_FIEL_TYPE_STR, SQL_FIEL_TYPE_INT};
	int res,count,i;
	ZB_Device_login dev_login;

	//sql数据生成
	memcpy((void *)&dev_login, (void *)msg->data, msg->count);
	//写入数据库
	str_transition_mac(dev_login.mac, dat_buf[0]);
	printf("login->%s\n", dat_buf[0]);
	sprintf(update_status, "{\"dev_status\":\"dev-online\",\"dev_mac\":\"%s\"}", dat_buf);

	//调试信息
	printf("count=%d size=%d type=%d\n", msg->count, sizeof(ZB_Device_login), dev_login.type);
	
	if(dev_login.type & (1<<ZB_COORD_LOGIN_IN))
	{
		//协调器入网 将表格中所以存在节点的状态设置为断线
		sprintf(status, "%d", ZB_DEV_OFFLINE);
		sql_update_column(devcfg_table, "dev_status", status, SQL_FIEL_TYPE_INT);
		
		dev_login.type = dev_login.type & (~(1<<ZB_COORD_LOGIN_IN));
		
	}

	//判断是否为第一次入网
	res = sql_query_field_exist(devcfg_table, "dev_mac", dat_buf[0], SQL_FIEL_TYPE_STR);
	if(res==0)
	{
		//表示设备在线
		update_intfield_value_by_strfield(devcfg_table, "dev_mac", dat_buf[0], "dev_status", ZB_DEV_ONLINE);
		server_msg_str_update(update_status);
        //voperation(sem_send_dev_online_list, g_sem_id);//websocket更新设备列表
	}
	else
	{
		printf("first insert\n");
		//向devcfg表格插入一行数据
		sprintf(dat_buf[1], "%s", "none");//dev_name
		sprintf(dat_buf[2], "%d", dev_login.type);//dev_type
		sprintf(dat_buf[3], "%s", "none");//dev_region
		sprintf(dat_buf[4], "%d", msg->cmd);//dev_status

		//count             = sprintf(dat_buf[3], "%d", ZB_DEV_ONLINE);
		//dat_buf[1][count] = '\0';
		insert_line_data(devcfg_table, dat_buf, type, 5);
		//voperation(sem_send_dev_online_list, g_sem_id);//websocket更新设备列表

		for(i=0; i<32; ++i)
		{
			//printf("%s-%s:%d\n", __FILE__, __FUNCTION__, __LINE__);
			if(dev_login.type & (1<<i))
			{
				//向对应的表格插入数据
				sprintf(dat_buf[1], "%s", "123");
				sprintf(dat_buf[2], "%s", "123");
				type[1] = SQL_FIEL_TYPE_INT;
				type[2] = SQL_FIEL_TYPE_INT;
				insert_line_data(sensor_table[i], dat_buf, type, 3);
			}
		}
	}
}

/*********************************************************************
 * @fn      zb_dev_offline_handle
 *
 * @brief   设备下线处理函数
 *
 * @param   msg:消息
 *
 * @return  none
 */
void zb_dev_offline_handle(uartmsg *msg)
{
	ZB_Device_logout dev_logout;
	char dat_buf[32];
	char update_status[128];

	memcpy((void *)&dev_logout, (void *)msg->data, msg->count);
	str_transition_mac(dev_logout.mac, dat_buf);
	sprintf(update_status, "{\"dev_status\":\"dev-offline\",\"dev_mac\":\"%s\"}", dat_buf);

	update_intfield_value_by_strfield(devcfg_table, "dev_mac", dat_buf, "dev_status", ZB_DEV_OFFLINE);
	server_msg_str_update(update_status);
	voperation(sem_send_dev_online_list, g_sem_id);//更新设备列表
	printf("logout->mac=%s\n", dat_buf);
}

/*********************************************************************
 * @fn      zb_sensor_light_handle
 *
 * @brief   灯光数据包处理函数
 *
 * @param   msg:消息
 *
 * @return  none
 */
void zb_sensor_light_handle(uartmsg *msg)
{
	Light_Ctrl_pkg light_pkg;
	char dat_buf[32];
    int res;

	//数据转化
	memcpy((void *)&light_pkg, (void *)msg->data, msg->count);
	str_transition_mac(light_pkg.mac, dat_buf);

	//更新灯光表格中的灯光状态
	res = update_intfield_value_by_strfield(sensor_table[msg->cmd], "dev_mac", dat_buf, "sensor_status", light_pkg.status);
	printf("updata:%d %s\n", res, sensor_table[msg->cmd]);
	server_msg_update(dat_buf, CMD_LIGHT);//websocket通知更新
	printf("light_response:%d\n", light_pkg.dev_response);
	WAIT_RES_ARRAY[light_pkg.dev_response] = 0;
}

/*********************************************************************
 * @fn      zb_sensor_llumination_handle
 *
 * @brief   光强数据包处理函数
 *
 * @param   msg:消息
 *
 * @return  none
 */
void zb_sensor_llumination_handle(uartmsg *msg)
{
	Illumination_pkg illumination_pkg;
	char dat_buf[32];

	//数据转化
	memcpy((void *)&illumination_pkg, (void *)msg->data, msg->count);
	str_transition_mac(illumination_pkg.mac, dat_buf);

	//更新灯光表格中的灯光状态
	update_intfield_value_by_strfield(sensor_table[msg->cmd], "dev_mac", dat_buf, "sensor_status", illumination_pkg.Illumination_data);
	server_msg_update(dat_buf, CMD_PSST);//websocket通知更新
}

/*********************************************************************
 * @fn      zb_sensor_temp_handle
 *
 * @brief   温度数据包处理函数
 *
 * @param   msg:消息
 *
 * @return  none
 */
void zb_sensor_temp_handle(uartmsg *msg)
{
	Temp_pkg temp_pkg;
	char dat_buf[32];

	//数据转化
	memcpy((void *)&temp_pkg, (void *)msg->data, msg->count);
	str_transition_mac(temp_pkg.mac, dat_buf);

	//更新灯光表格中的灯光状态
	update_intfield_value_by_strfield(sensor_table[msg->cmd], "dev_mac", dat_buf, "sensor_status", temp_pkg.Temp_data);
	server_msg_update(dat_buf, CMD_TEMPERATURE);//websocket通知更新
}

/*********************************************************************
 * @fn      zb_sensor_humidity_handle
 *
 * @brief   湿度数据包处理函数
 *
 * @param   msg:消息
 *
 * @return  none
 */
void zb_sensor_humidity_handle(uartmsg *msg)
{
	Humidity_pkg humidity_pkg;
	char dat_buf[32];

	//数据转化
	memcpy((void *)&humidity_pkg, (void *)msg->data, msg->count);
	str_transition_mac(humidity_pkg.mac, dat_buf);

	//更新灯光表格中的灯光状态
	update_intfield_value_by_strfield(sensor_table[msg->cmd], "dev_mac", dat_buf, "sensor_status", humidity_pkg.Humidity_data);
	server_msg_update(dat_buf, CMD_HUMIDITY);//websocket通知更新
}

/*********************************************************************
 * @fn      zb_sensor_door_handle
 *
 * @brief   门数据包处理函数
 *
 * @param   msg:消息
 *
 * @return  none
 */
void zb_sensor_door_handle(uartmsg *msg)
{
	Door_pkg door_pkg;
	char dat_buf[32];

	//数据转化
	memcpy((void *)&door_pkg, (void *)msg->data, msg->count);
	str_transition_mac(door_pkg.mac, dat_buf);

	//更新灯光表格中的灯光状态
	update_intfield_value_by_strfield(sensor_table[msg->cmd], "dev_mac", dat_buf, "sensor_status", door_pkg.status);
	server_msg_update(dat_buf, CMD_DOOR);//websocket通知更新
	printf("door response:%d\n", door_pkg.dev_response);
	WAIT_RES_ARRAY[door_pkg.dev_response] = 0;
}

/*********************************************************************
 * @fn      zb_sensor_fan_handle
 *
 * @brief   风扇数据包处理函数
 *
 * @param   msg:消息
 *
 * @return  none
 */
void zb_sensor_fan_handle(uartmsg *msg)
{
	Fan_pkg fan_pkg;
	char dat_buf[32];

	//数据转化
	memcpy((void *)&fan_pkg, (void *)msg->data, msg->count);
	str_transition_mac(fan_pkg.mac, dat_buf);

	//更新灯光表格中的灯光状态
	update_intfield_value_by_strfield(sensor_table[msg->cmd], "dev_mac", dat_buf, "sensor_status", fan_pkg.status);
	server_msg_update(dat_buf, CMD_RELAY);//websocket通知更新
	printf("fan response:%d\n", fan_pkg.dev_response);
	WAIT_RES_ARRAY[fan_pkg.dev_response] = 0;
}

/*********************************************************************
 * @fn      zb_sensor_beep_handle
 *
 * @brief   蜂鸣器数据包处理函数
 *
 * @param   msg:消息
 *
 * @return  none
 */
void zb_sensor_beep_handle(uartmsg *msg)
{
	Beep_pkg beep_pkg;
	char dat_buf[32];

	//数据转化
	memcpy((void *)&beep_pkg, (void *)msg->data, msg->count);
	str_transition_mac(beep_pkg.mac, dat_buf);

	//更新灯光表格中的灯光状态
	update_intfield_value_by_strfield(sensor_table[msg->cmd], "dev_mac", dat_buf, "sensor_status", beep_pkg.status);
	server_msg_update(dat_buf, CMD_BEEP);//websocket通知更新
	printf("beep response:%d\n", beep_pkg.dev_response);
	WAIT_RES_ARRAY[beep_pkg.dev_response] = 0;
}

/*********************************************************************
 * @fn      zb_sensor_smoke_handle
 *
 * @brief   烟雾数据包处理函数
 *
 * @param   msg:消息
 *
 * @return  none
 */
void zb_sensor_smoke_handle(uartmsg *msg)
{
	Smoke_pkg smoke_pkg;
	char dat_buf[32];
	char alarm_message[128]="8b6662a5ff01706b707eff01";//警报！火灾！
	//char alarm_message[128]="4f5957f968ee725b903cff01";

	//数据转化
	memcpy((void *)&smoke_pkg, (void *)msg->data, msg->count);
	str_transition_mac(smoke_pkg.mac, dat_buf);

	//更新灯光表格中的灯光状态
	update_intfield_value_by_strfield(sensor_table[msg->cmd], "dev_mac", dat_buf, "sensor_status", smoke_pkg.status);
	server_msg_update(dat_buf, CMD_SMOKE);//websocket通知更新
	if(smoke_pkg.status==1)
	{
		gprs_send_message_to_emergency_call(alarm_message);
	}
}

/*********************************************************************
 * @fn      zb_sensor_calorifier_handle
 *
 * @brief   热水器数据包处理函数
 *
 * @param   msg:消息
 *
 * @return  none
 */
void zb_sensor_calorifier_handle(uartmsg *msg)
{
	Calorifier_pkg calorifier_pkg;
	char dat_buf[32];

	//数据转化
	memcpy((void *)&calorifier_pkg, (void *)msg->data, msg->count);
	str_transition_mac(calorifier_pkg.mac, dat_buf);

	//更新灯光表格中的灯光状态
	update_intfield_value_by_strfield(sensor_table[msg->cmd], "dev_mac", dat_buf, "sensor_status", calorifier_pkg.status);
	server_msg_update(dat_buf, CMD_CALORIFIER);//websocket通知更新
	WAIT_RES_ARRAY[calorifier_pkg.dev_response] = 0;
}

/*********************************************************************
 * @fn      zb_sensor_curtain_handle
 *
 * @brief   窗帘数据包处理函数
 *
 * @param   msg:消息
 *
 * @return  none
 */
void zb_sensor_curtain_handle(uartmsg *msg)
{
	Curtain_pkg curtain_pkg;
	char dat_buf[32];

	//数据转化
	memcpy((void *)&curtain_pkg, (void *)msg->data, msg->count);
	str_transition_mac(curtain_pkg.mac, dat_buf);

	//更新灯光表格中的灯光状态
	update_intfield_value_by_strfield(sensor_table[msg->cmd], "dev_mac", dat_buf, "sensor_status", curtain_pkg.status);
	server_msg_update(dat_buf, CMD_CURTAIN);//websocket通知更新
	printf("curtain response:%d\n", curtain_pkg.dev_response);
	WAIT_RES_ARRAY[curtain_pkg.dev_response] = 0;
}
